/*
 * AccountDetails.cpp
 *
 *  Created on: 28.05.2009
 *      Author: h3llfire
 */

#include "AccountDetails.h"

#include "../../core/Impp.h"
#include "StatusMessageDialog.h"

namespace Impp {

BEGIN_EVENT_TABLE(AccountDetails, wxPanel)
	EVT_TOOL_RANGE(ID_STATUS_ONLINE, ID_STATUS_OFFLINE, AccountDetails::onStatusSelected)
	EVT_TOOL_RANGE(ID_STATUS_EXTENDED_START, ID_STATUS_EXTENDED_END, AccountDetails::onExtendedStatusSelected)
	EVT_TOOL(ID_STATUS_MESSAGE, AccountDetails::onStatusMessage)
END_EVENT_TABLE()


AccountDetails::AccountDetails(wxWindow* parent) :
	wxPanel(parent),
	lastIconId(-1),
	curDisplayedAccount(NULL){

	Impp* impp = Impp::exemplar();

	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	if(ui == NULL){
		wxLogError(wxT("AccountDetails: No userinterface found, can not create AccountDetails"));
	}

	wxString shownName;
	wxBitmap shownAvatar;

	std::vector<Account*> accounts;
	impp->getActiveAccounts(accounts);

	if(accounts.size() == 0){
		shownAvatar = ui->getIcons()->getSpecialBitmap(BITMAP_NO_AVATAR);
	}else{
		curDisplayedAccount  = accounts[0];
		Buddy* self = curDisplayedAccount->self;

		//Avatar
		shownAvatar = self->getAvatar();

		if(shownAvatar.IsNull()){
			shownAvatar = ui->getIcons()->getSpecialBitmap(BITMAP_NO_AVATAR);
		}

		shownName = self->getName();
	}

	wxBoxSizer* infoStatusMsgSizer = new wxBoxSizer(wxVERTICAL);
	wxBoxSizer* avatarStatusSizer = new wxBoxSizer(wxHORIZONTAL);
	statusIconSizer = new wxBoxSizer(wxHORIZONTAL);
	wxBoxSizer* nameStatusSizer = new wxBoxSizer(wxVERTICAL);

	recreateStatusIcons();

	//Name
	screenName = new wxStaticText(this,wxID_ANY,shownName);
	wxFont f = screenName->GetFont();
	f.SetWeight(wxFONTWEIGHT_BOLD);
	screenName->SetFont(f);
	//StatusIcon

	//StatusTxt
	//statusTxt = new wxStaticText(this,ID_TEXT_STATUS,statusToString(OFFLINE));
	//StatusMsg

	statusMsg = new wxStaticText(this,ID_TEXT_STATUS_MSG,wxT("No Status Message"),wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
	statusMsg->Hide();

	wxImage image = shownAvatar.ConvertToImage();
	wxBitmap avaScaled = wxBitmap(image.Scale(36,36,wxIMAGE_QUALITY_HIGH));
	ownAvatar = new wxStaticBitmap(this,wxID_ANY,avaScaled);

	//Layout


	nameStatusSizer->Add(screenName,0,wxEXPAND|wxBOTTOM,2);
	nameStatusSizer->Add(statusIconSizer,0,wxEXPAND|wxALL,0);

	avatarStatusSizer->Add(ownAvatar,0,wxEXPAND|wxTOP,3);
	avatarStatusSizer->Add(nameStatusSizer,0,wxEXPAND|wxLEFT,5);

	infoStatusMsgSizer->Add(avatarStatusSizer,0,wxEXPAND|wxALL,0);
	infoStatusMsgSizer->Add(statusMsg,0,wxEXPAND|wxALL,0);

	SetSizer(infoStatusMsgSizer);
	Layout();


	//statusTxt->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(BuddyList::onStatusMouseDown),NULL, this);
	//statusTxt->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(BuddyList::onStatusMouseDown),NULL, this);

	//statusMsgTxt->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(AccountDetails::onStatusMsgMouseDown),NULL, this);
	//statusMsgTxt->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(AccountDetails::onStatusMsgMouseDown),NULL, this);
	ownAvatar->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(AccountDetails::onAvatarMouseDown),NULL, this);

    impp->Connect(EVT_SELF_CHANGED,SelfChangedEventHandler(AccountDetails::onSelfChanged), NULL, this);
    impp->Connect(EVT_OWN_AVATAR_CHANGED,AvatarChangedEventHandler(AccountDetails::onOwnAvatarChanged), NULL, this);
    impp->Connect(EVT_OWN_STATUS_CHANGED,StatusEventHandler(AccountDetails::onOwnStatusChanged), NULL, this);
    impp->Connect(EVT_ACCOUNT,AccountEventHandler(AccountDetails::onAccountEvent), NULL, this);

}

AccountDetails::~AccountDetails() {

}

void AccountDetails::recreateStatusIcons(){
	Impp* impp = Impp::exemplar();

	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	if(ui == NULL){
		wxLogError(wxT("AccountDetails: No userinterface found, can not create AccountDetails"));
		return;
	}

	//Delete old
	for(size_t i = 0; i < icons.size(); i++){
		AccountIcon* accountIcon = icons[i];
		ImppBitmapButton* statusIcon = accountIcon->statusIcon;
		statusIcon->Disconnect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(AccountDetails::onStatusMouseDown),NULL, this);
		statusIcon->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(AccountDetails::onStatusMouseDown),NULL, this);
		statusIcon->Disconnect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(AccountDetails::onStatusMouseOver), NULL, this);
		statusIcon->Disconnect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(AccountDetails::onStatusMouseOver), NULL, this);
		statusIconSizer->Detach(statusIcon);
		delete accountIcon;
	}
	icons.clear();

	std::vector<Account*> accounts;
	impp->getActiveAccounts(accounts);

	std::vector<Account*>::iterator ia;
	size_t i = 0;

	for(ia = accounts.begin(); ia != accounts.end(); ia++){
		Account* a = *ia;
		ImppBitmapButton* statusIcon = new ImppBitmapButton(this,ACCOUNT_DETAILS_ID_STATUS_ICON + i ,ui->getIcons()->getStatusIcon(OFFLINE), wxDefaultPosition, wxSize(22,22));
		statusIcon->setNoPadding();
		i++;
		icons.push_back(new AccountIcon(a, statusIcon));
		statusIconSizer->Add(statusIcon,0,wxSHAPED|wxRIGHT);
		statusIcon->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(AccountDetails::onStatusMouseDown),NULL, this);
		statusIcon->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(AccountDetails::onStatusMouseDown),NULL, this);
		statusIcon->Connect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(AccountDetails::onStatusMouseOver), NULL, this);
		statusIcon->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(AccountDetails::onStatusMouseOver), NULL, this);
	}

	Layout();
}

void AccountDetails::onStatusMouseDown(wxMouseEvent& event){
	int id  = event.GetId() - ACCOUNT_DETAILS_ID_STATUS_ICON;

	if(id < 0 || id > (int) icons.size()){
		wxLogDebug(wxT("AccountDetails::onStatusMouseDown illegal id"));
		lastIconId = -1;
	}else{
		lastIconId = id;
	}

	Account* acc = icons[lastIconId]->account;

	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	if(ui != NULL){


		if(event.GetButton() == wxMOUSE_BTN_RIGHT){
			wxPoint pos = event.GetPosition();
			wxMenu menu;
			ui->buildChooseStatusMenu(&menu, acc, acc->protocol->getPrivacySettings() != PRICACY_BLOCK_ONLY_DENYLIST);
			menu.Append(ID_STATUS_MESSAGE, wxT("Status Message"));
			PopupMenu(&menu);
		}else if(event.GetButton() == wxMOUSE_BTN_LEFT){
			iBuddyList* bl = Impp::exemplar()->getModuleManager()->getBuddyListModule();
			if(bl != NULL){
				new StatusMessageDialog(dynamic_cast<BuddyList*>(bl->getWindow()), acc->id);
			}else{
				wxLogError(wxT("AccountDetails::onStatusMouseDown: Coudn't show StatusMessageDialog no BuddylistModule loaded"));
			}
		}

		statusMsg->Hide();

		iBuddyList* bl = Impp::exemplar()->getModuleManager()->getBuddyListModule();
		if(bl != NULL){
			BuddyList* rbl = dynamic_cast<BuddyList*>(bl->getWindow());
			rbl->layoutMainSizer();
		}

	}else{
		wxLogError(wxT("AccountDetails::onStatusMsgMouseDown: Coudn't build Status Menu no UserInterfaceModule loaded"));
	}

    event.Skip();
}

void AccountDetails::onStatusMouseOver(wxMouseEvent& event){
	event.Skip();


	iBuddyList* bl = Impp::exemplar()->getModuleManager()->getBuddyListModule();
	if(bl != NULL){
		BuddyList* rbl = dynamic_cast<BuddyList*>(bl->getWindow());

		if(event.GetEventType() == wxEVT_ENTER_WINDOW){

			int id  = event.GetId() - ACCOUNT_DETAILS_ID_STATUS_ICON;

			if(id < 0 || id > (int) icons.size()){
				wxLogDebug(wxT("AccountDetails::onStatusMouseOver illegal id: %i"), id);
				return;
			}

			curDisplayedAccount = icons[id]->account;

			updateStatusMessageLabel(curDisplayedAccount->self);
			updateAvatarBitmap(curDisplayedAccount->self);
			updateNameLabel(curDisplayedAccount->self);

			statusMsg->Show();
			rbl->layoutMainSizer();
		}else if(event.GetEventType() == wxEVT_LEAVE_WINDOW){
			statusMsg->Hide();
			rbl->layoutMainSizer();
		}

	}else{
		wxLogError(wxT("AccountDetails::onStatusMouseOver: Coudn't show status msg, no BuddylistModule loaded"));
	}


}

void AccountDetails::updateStatusMessageLabel(Buddy* self){
    wxString statusMsgTxt = self->getStatusMsg();

    if(statusMsgTxt.Length() > 20){
    	statusMsgTxt = statusMsgTxt.SubString(0,20) << wxT("...");
    }

    wxFont f = statusMsg->GetFont();
    if(statusMsgTxt.IsEmpty()){
        statusMsg->SetLabel(wxT("No Status Message"));
    	f.SetStyle(wxFONTSTYLE_ITALIC);
    	statusMsg->SetFont(f);
    }else{
        statusMsg->SetLabel(statusMsgTxt);
    	f.SetStyle(wxFONTSTYLE_NORMAL);
    	statusMsg->SetFont(f);
    }
}

void AccountDetails::updateAvatarBitmap(Buddy* self){


	wxBitmap ownAvatarBitmap = self->getAvatar();
	if(ownAvatarBitmap.IsNull()){
		iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
		if(ui == NULL){
			wxLogError(wxT("AccountDetails: No userinterface found, can not create AccountDetails"));
			return;
		}
		ownAvatarBitmap = ui->getIcons()->getSpecialBitmap(BITMAP_NO_AVATAR);
	}

	wxImage image = ownAvatarBitmap.ConvertToImage();
	wxBitmap avaScaled = wxBitmap(image.Scale(36,36,wxIMAGE_QUALITY_HIGH));
	ownAvatar->SetBitmap(avaScaled);
}

void AccountDetails::updateNameLabel(Buddy* self){
	screenName->SetLabel(self->getName());
	screenName->Refresh();
}

void AccountDetails::onStatusMessage(wxCommandEvent& event){
	event.Skip();
	if(lastIconId == -1){
		wxLogDebug(wxT("AccountDetails::onStatusMessage: illegal lastIconId"));
		return;
	}

	iBuddyList* bl = Impp::exemplar()->getModuleManager()->getBuddyListModule();
	if(bl != NULL){
		new StatusMessageDialog(dynamic_cast<BuddyList*>(bl->getWindow()), icons[lastIconId]->account->id);
	}else{
		wxLogError(wxT("AccountDetails::onStatusMsgMouseDown: Coudn't build Status Menu no BuddylistModule loaded"));
	}
}

void AccountDetails::onAvatarMouseDown(wxMouseEvent& event){

	if(curDisplayedAccount == NULL){
		return;
	}

	wxFileDialog dia(this,wxFileSelectorPromptStr,wxEmptyString,wxEmptyString,
            wxT("JPEG, GIF and PNG files (*.jpg;*.gif;*.png)|*.jpg;*.jpeg;*.gif;*.png;*.JPG;*.JPEG;*.GIF;*.PNG"),wxOPEN);

	if(dia.ShowModal() == wxID_OK){
		Impp::exemplar()->changeOwnAvatar(curDisplayedAccount->id, dia.GetPath());

	}
}

void AccountDetails::onSelfChanged(SelfChangedEvent & event){
	event.Skip();

	if(curDisplayedAccount == NULL){
		return;
	}

	if(event.getSelf() == curDisplayedAccount->self){
		switch (event.GetEventType()) {
			case SELF_CHANGED_CUSTOMNAME:
			case SELF_CHANGED_SCREENNAME:
			default:
				updateNameLabel(curDisplayedAccount->self);
				break;
		}
	}


}

void AccountDetails::onOwnAvatarChanged(AvatarChangedEvent & event){
	event.Skip();

	if(curDisplayedAccount == NULL){
		return;
	}

	if(event.getBuddy() == curDisplayedAccount->self){
		updateAvatarBitmap(curDisplayedAccount->self);
	}

}

void AccountDetails::onStatusSelected(wxCommandEvent & event){
	Impp* impp = Impp::exemplar();

	if(lastIconId == -1){
		event.Skip();
		wxLogDebug(wxT("AccountDetails::onStatusSelected: illegal lastIconId"));
		return;
	}

	Status status = UNKNOWN;
	PrivacySetting privacy = PRICACY_INVALID;

	switch (event.GetId()) {
		case ID_STATUS_ONLINE:
			status = ONLINE;
			break;
		case ID_STATUS_FREE4CHAT:
			status = FREE4CHAT;
			break;
		case ID_STATUS_AWAY:
			status =AWAY;
			break;
		case ID_STATUS_OCCUPIED:
			status = OCCUPIED;
			break;
		case ID_STATUS_DND:
			status = DND;
			break;
		case ID_STATUS_NA:
			status = NA;
			break;
		case ID_STATUS_OFFLINE:
			status = OFFLINE;
			break;
		case ID_STATUS_VISIBLE:
			privacy = PRICACY_BLOCK_ONLY_DENYLIST;
			break;
		case ID_STATUS_INVISIBLE:
			privacy = PRICACY_ALLOW_ONLY_PERMITLIST;
			break;
		default:
			break;
	}

	Account* acc = icons[lastIconId]->account;
	Buddy* self = acc->self;


	//handle status change:
	if(privacy == PRICACY_INVALID){
		//just status was changed so handle it:
		int xstatus = self->getStatus().getExtraStatus();
		status.setExtraStatus(xstatus);



		privacy = impp->getPrivacySettings(acc->id);
		impp->setStatusAndChageState(acc->id, status,self->getStatusMsg(),privacy);

	}else{
		wxLogDebug(wxT("setting Account id: %i Privacy is: %i"), acc->id.ToLong(), privacy);

		//handle privacy changed:
		impp->setPrivacySettings(acc->id, privacy);
	}

}

void AccountDetails::onExtendedStatusSelected(wxCommandEvent & event){
	int xstatus = event.GetId() -ID_STATUS_EXTENDED_START;

	if(lastIconId == -1){
		event.Skip();
		wxLogDebug(wxT("AccountDetails::onExtendedStatusSelected: illegal lastIconId"));
		return;
	}

	Account* acc = icons[lastIconId]->account;
	Buddy* self = acc->self;

	Status status = self->getStatus();
	status.setExtraStatus(xstatus);

	Impp::exemplar()->setStatus(acc->id, status, self->getStatusMsg());

}

void AccountDetails::onOwnStatusChanged(StatusEvent & event){
	event.Skip();


	Status status = event.getNewStatus();

	Buddy* self = event.getBuddy();
	AccountIcon* icon = NULL;

	std::vector<AccountIcon*>::iterator ii;
	for(ii = icons.begin(); ii != icons.end(); ii++){
		AccountIcon* i = *ii;
		if(i->account->id == self->getAccountId()){
			icon = i;
			break;
		}
	}

	if(icon == NULL){
		wxLogDebug(wxT("AccountDetails::onOwnStatusChanged: No AccountIcon for this Event found!"));
		return;
	}

	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	if(ui != NULL){
		icon->statusIcon->SetBitmapLabel(ui->getIcons()->getStatusIcon(status));
	}else{
		wxLogError(wxT("AccountDetails::onOwnStatusChanged: Coudn't update no UserInterfaceModule loaded"));
	}


/*
	statusTxt->SetLabel(statusToString(status));
	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	wxASSERT(ui != NULL);
    statusIcon
*/

}

void AccountDetails::onAccountEvent(AccountEvent & event){
	event.Skip();
	switch(event.getAccountEventType()){
		case ACCOUNT_EVENT_ACCOUNT_DELETED:
		case ACCOUNT_EVENT_ACCOUNT_DEACTIVATED:
			if(event.getAccount() == curDisplayedAccount){
				curDisplayedAccount = NULL;
			}
		case ACCOUNT_EVENT_NEW_ACCOUNT:
		case ACCOUNT_EVENT_ACCOUNT_ACTIVATED:

			recreateStatusIcons();
		case ACCOUNT_EVENT_ACCOUNT_CHANGED:
			if(curDisplayedAccount == event.getAccount()){
				updateNameLabel(curDisplayedAccount->self);
			}

	}
}

}
